/////////////////////////////////////////////////////////
////												 ////
////	SPI Master interface						 ////
////												 ////
////	Author: Li Shenyu							 ////
////    Beijing institute of technology	   			 ////
////	pxlsy2000@gmail.com							 ////
////												 ////
////												 ////
/////////////////////////////////////////////////////////

module spi_fifo
(
  clk,
  rst,
  clr,
  data_in,
  data_out,
  write,
  read,
  full,
  empty

);

input		  clk;
input		  rst;
input		  clr;
input   [7:0] data_in;
output  [7:0] data_out;
input		  write;
input  		  read;
output	      full;
output	 	  empty;

wire 	      full;
wire 		  empty;

reg 	[7:0] mem [3:0];
reg	    [1:0] write_ptr;
reg		[1:0] read_ptr;
reg		[2:0] counter;

//read
assign data_out = (rst|clr) ? 8'b0 : mem[read_ptr];

//write
always @ (posedge clk, posedge rst)
begin
  if(!rst & write)
   mem[write_ptr] <= data_in;
end

//write_ptr
always@(posedge clk, posedge rst)
begin
  if(rst)
  	write_ptr <= 2'd0;
  else if(clr)
  	write_ptr <= 2'd0;
  else if (write & !full)
  	write_ptr <= write_ptr + 1;
end

//read_ptr
always@(posedge clk, posedge rst)
begin
  if(rst)
  	read_ptr <= 2'd0;
  else if(clr)
  	read_ptr <= 2'd0;
  else if (read & !empty)
    read_ptr <= read_ptr + 1;
end

//counter
always@(posedge clk, posedge rst)
begin
  if(rst)
  	counter <= 3'd0;
  else if (clr)
    counter <= 3'd0;
  else 
  	case({read,write})
	3'b00:	//no read and no write
		counter <= counter;
	3'b01:	//only write happend
		if (!full)
		  counter <= counter + 1;
	3'b10:
	  	if (!empty)
		  counter <= counter - 1;
  	3'b11:
		counter <= counter;
	endcase
end

//full and empty signal
assign full = (counter == 4) ? 1'b1 : 1'b0;
assign empty = (counter == 0) ? 1'b1 : 1'b0;

endmodule
